package com.xuecheng.message.sdk.service;

import com.xuecheng.message.sdk.model.po.MqMessage;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.*;

/**
 * @author 勾新杰
 * @version 1.0
 * @description 消息处理抽象类
 * @date 2025/2/17 19:44
 */
@Data
@Slf4j
@RequiredArgsConstructor
public abstract class MessageProcessAbstract {

    // 模板方法模式的设计模式

    /**
     * 消息服务
     */
    private final IMqMessageService mqMessageService;

    /**
     * 执行任务内容
     * @param mqMessage 执行任务内容
     * @return boolean true:处理成功，false处理失败
     */
    public abstract boolean execute(MqMessage mqMessage);

    /**
     * 任务处理模板
     *
     * @param shardIndex  分片序号
     * @param shardTotal  分片总数
     * @param messageType 消息类型
     * @param count       一次扫描消息表获取记录数
     * @param timeout     超时时间
     */
    public void process(int shardIndex, int shardTotal, String messageType, int count, long timeout) {
        try {
            // 扫描消息表获取任务清单
            List<MqMessage> messageList = mqMessageService.getMessageList(shardIndex, shardTotal, messageType, count);
            // 任务个数
            int size = messageList.size();
            log.debug("取出待处理消息" + size + "条");
            if (size == 0) return;
            // 创建线程池、计数器
            ExecutorService threadPool = Executors.newFixedThreadPool(size);
            CountDownLatch countDownLatch = new CountDownLatch(size);
            messageList.forEach(message -> threadPool.execute(() -> {
                log.debug("开始任务:{}", message);
                boolean result = execute(message);
                if (result) log.debug("任务执行成功，任务:{}", message);
                else log.error("任务执行失败，任务:{}", message);
                countDownLatch.countDown();
                log.debug("任务结束:{}", message);
            }));
            // 等待,给一个充裕的超时时间,防止无限等待，到达超时时间还没有处理完成则结束任务
            boolean await = countDownLatch.await(timeout, TimeUnit.SECONDS);
            if (!await) log.error("视频处理任务超时");
        } catch (InterruptedException e) {
            log.error("扫描消息表多线程执行任务出错:{}", e.getMessage());
        }
    }
}
